/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cuatroenraya.jugadores;

import cuatroenraya.util.HeuristicaList;
import java.util.ArrayList;

/**
 *
 * @author Dario
 */
public class Node {

    public ArrayList<Node> Hijos = new ArrayList<Node>();
    public Node ancestro;   // Nodo Padre
    public int Puntuacion;
    private int tamFilasTablero = 8;
    private int tamColTablero = 8;
    private int[][] tablero;
    private Jugada jugada;
    private int fichaJugador;
    private Posicion pInicioGlobal = new Posicion();
    private static HeuristicaList hl = new HeuristicaList();
    private ArrayList<Posicion> oponenteLocal = new ArrayList<Posicion>();
    private ArrayList<Posicion> miasLocal = new ArrayList<Posicion>();

    // Constructor
    public Node() {
        Hijos = new ArrayList<Node>();
        Puntuacion = 0;
        jugada = new Jugada();

    }

    public int getFichaJugador() {
        return fichaJugador;
    }

    public void setFichaJugador(int fichaJugador) {
        this.fichaJugador = fichaJugador;
    }

    public Jugada getJugada() {
        return jugada;
    }

    public void setJugada(Jugada jugada) {
        this.jugada = jugada;
    }

    public Node(int[][] tablero, int fichaJugador) {

        this.tablero = tablero;
        //puntuarJugada(tablero, mejorJugada, fichaJugador, esMover);
        this.fichaJugador = fichaJugador;


    }

    public Node(int[][] tablero, int fichaJugador, boolean esMover, Jugada jug) {

        Hijos = new ArrayList<Node>();
        //this.tablero = tablero.clone();
        this.fichaJugador = fichaJugador;
        this.jugada = jug;

    }

    public int[][] getTablero() {
        return tablero;
    }

    public void setTablero(int[][] tablero) {
        this.tablero = tablero;
    }

    public void setPuntuacion(int Puntuacion) {
        this.Puntuacion = Puntuacion;
    }

    public void setAncestro(Node ancestro) {
        this.ancestro = ancestro;
    }

    public static HeuristicaList getHl() {
        return hl;
    }

    public static void setHl(HeuristicaList hl) {
        Node.hl = hl;
    }
    int a = 1;

    public Posicion addNodoHijosInsertar(Node padre, int FichaJugador,
            Posicion p) {

        int[][] tablero_padre = new int[8][8];
        tablero_padre = padre.tablero;
        Node n = new Node(tablero_padre, FichaJugador);
        n.setAncestro(padre);
        int[][] tablero_hijo = clonar(tablero_padre);
        Posicion[] aux = crearInserciones(tablero_hijo, p);
        n.setTablero(tablero_hijo);
        pInicioGlobal.setX(-1);
        pInicioGlobal.setY(-1);
        Arbol.setHijo(n);
        Jugada j = new Jugada(pInicioGlobal, aux[0]);

        n.setJugada(j);
        heuristica h = new heuristica();
        actualizarListasPadre(padre);
        h.heuristica1(n, hl, miasLocal, oponenteLocal);

        System.out.println("INSERCION N° " + a + " " + aux[0].getY() + "    "
                + aux[0].getX());
        System.out.println("HEURISTICA: " + n.Puntuacion);
        System.out.println("Proxima: " + aux[1].getY() + " " + aux[1].getX());
        a++;
        p = aux[1];
        return p;
    }

    public void addNodoHijosMover(Node padre, int FichaJugador, boolean oponente) {
        if (!oponente) {
            ArrayList<Posicion> posiciones = Arbol.getMisFichas();
            for (Posicion posicion : posiciones) {
                moverFichas(posicion, padre, FichaJugador);
            }
        } else {
            ArrayList<Posicion> posiciones = Arbol.getFichasOponente();
            for (Posicion posicion : posiciones) {
                moverFichas(posicion, padre, FichaJugador);
            }
        }


    }

    private int[][] clonar(int[][] tablero) {
        int[][] clon = null;
        clon = new int[tablero.length][tablero.length];
        for (int i = 0; i < clon.length; i++) {
            for (int j = 0; j < clon.length; j++) {
                clon[i][j] = tablero[i][j];
            }
        }
        return clon;
    }

    //<editor-fold defaultstate="collapsed" desc="MOVIMIENTOS FICHAS">
    public void moverFichas(Posicion p, Node padre, int FichaJugador) {
        moverAbajo(p, padre, FichaJugador);
        moverArriba(p, padre, FichaJugador);
        moverDerecha(p, padre, FichaJugador);
        moverIzquierda(p, padre, FichaJugador);
        ascendenteDerecha(p, padre, FichaJugador);
        ascendenteIzquierdo(p, padre, FichaJugador);
        desendenteDerecha(p, padre, FichaJugador);
        desendenteIzquierdo(p, padre, FichaJugador);
    }
    static int hh = 0;

    private void mostrarMoviminetos(Posicion pInicial, Posicion pfinal, Node n) {

        System.out.println("MOVER FICHA ORIGEN: " + pInicial.getY() + "    "
                + pInicial.getX());
        System.out.println("MOVER FICHA FINAL: " + pfinal.getY() + "    "
                + pfinal.getX());
        System.out.println("HEURISTICA MOVER: " + n.Puntuacion);
//        if (hh == 1868) {
//            System.out.println("ACA");
//        }
        System.out.println("HIJO N°: " + hh++);

    }

    private void moverIzquierda(Posicion p, Node padre, int FichaJugador) {

        int[][] tablero_padre = clonar(padre.getTablero());
        Node n = new Node(tablero_padre, FichaJugador);
        n.setAncestro(padre);
        int[][] tablero_hijo = n.getTablero();

        if (p.getX() != 0 && tablero_hijo[p.getY()][p.getX() - 1] == 0) {
            Arbol.setHijo(n);
            tablero_hijo[p.getY()][p.getX()] = 0;
            tablero_hijo[p.getY()][p.getX() - 1] = fichaJugador;
            Posicion pfinal = new Posicion(p.getX() - 1, p.getY());
            Jugada j = new Jugada(p, pfinal);
            n.setJugada(j);
            heuristica h = new heuristica();
            actualizarListasPadre(padre);
            h.heuristica1(n, hl, miasLocal, oponenteLocal);
            n.setTablero(tablero_hijo);
            mostrarMoviminetos(p, pfinal, n);
        }
    }

    private void moverDerecha(Posicion p, Node padre, int FichaJugador) {

        int[][] tablero_padre = clonar(padre.getTablero());
        Node n = new Node(tablero_padre, FichaJugador);
        n.setAncestro(padre);
        int[][] tablero_hijo = n.getTablero();
        if (p.getX() != 7 && tablero_hijo[p.getY()][p.getX() + 1] == 0) {
            Arbol.setHijo(n);
            tablero_hijo[p.getY()][p.getX()] = 0;
            tablero_hijo[p.getY()][p.getX() + 1] = fichaJugador;
            Posicion pfinal = new Posicion(p.getX() + 1, p.getY());
            Jugada j = new Jugada(p, pfinal);
            n.setJugada(j);
            heuristica h = new heuristica();
            actualizarListasPadre(padre);
            h.heuristica1(n, hl, miasLocal, oponenteLocal);
            n.setTablero(tablero_hijo);
            mostrarMoviminetos(p, pfinal, n);
        }
    }

    private void moverArriba(Posicion p, Node padre, int FichaJugador) {
        int[][] tablero_padre = clonar(padre.getTablero());
        Node n = new Node(tablero_padre, FichaJugador);
        n.setAncestro(padre);
        int[][] tablero_hijo = n.getTablero();
        if (p.getY() != 0 && tablero_hijo[p.getY() - 1][p.getX()] == 0) {
            Arbol.setHijo(n);
            tablero_hijo[p.getY()][p.getX()] = 0;
            tablero_hijo[p.getY() - 1][p.getX()] = fichaJugador;
            Posicion pfinal = new Posicion(p.getX(), p.getY() - 1);
            Jugada j = new Jugada(p, pfinal);
            n.setJugada(j);
            heuristica h = new heuristica();
            actualizarListasPadre(padre);
            h.heuristica1(n, hl, miasLocal, oponenteLocal);
            n.setTablero(tablero_hijo);
            mostrarMoviminetos(p, pfinal, n);
        }
    }

    private void moverAbajo(Posicion p, Node padre, int FichaJugador) {
        int[][] tablero_padre = clonar(padre.getTablero());
        Node n = new Node(tablero_padre, FichaJugador);
        n.setAncestro(padre);        
        int[][] tablero_hijo = n.getTablero();
        if (p.getY() != 7 && tablero_hijo[p.getY() + 1][p.getX()] == 0) {
            Arbol.setHijo(n);
            tablero_hijo[p.getY()][p.getX()] = 0;
            tablero_hijo[p.getY() + 1][p.getX()] = fichaJugador;
            Posicion pfinal = new Posicion(p.getX(), p.getY() + 1);
            Jugada j = new Jugada(p, pfinal);
            n.setJugada(j);
            heuristica h = new heuristica();
            actualizarListasPadre(padre);
            h.heuristica1(n, hl, miasLocal, oponenteLocal);
            n.setTablero(tablero_hijo);
            mostrarMoviminetos(p, pfinal, n);
        }
    }

    private void desendenteDerecha(Posicion p, Node padre, int FichaJugador) {
        int[][] tablero_padre = clonar(padre.getTablero());
        Node n = new Node(tablero_padre, FichaJugador);
        n.setAncestro(padre);
        int[][] tablero_hijo = n.getTablero();
        if (p.getY() != 7 && p.getX() != 7 && tablero_hijo[p.getY() + 1][p.getX()
                + 1] == 0) {
            Arbol.setHijo(n);
            tablero_hijo[p.getY()][p.getX()] = 0;
            tablero_hijo[p.getY() + 1][p.getX() + 1] = fichaJugador;
            Posicion pfinal = new Posicion(p.getX() + 1, p.getY() + 1);
            Jugada j = new Jugada(p, pfinal);
            n.setJugada(j);
            heuristica h = new heuristica();
            actualizarListasPadre(padre);
            h.heuristica1(n, hl, miasLocal, oponenteLocal);
            n.setTablero(tablero_hijo);
            mostrarMoviminetos(p, pfinal, n);
        }
    }

    private void desendenteIzquierdo(Posicion p, Node padre, int FichaJugador) {
        int[][] tablero_padre = clonar(padre.getTablero());
        Node n = new Node(tablero_padre, FichaJugador);
        n.setAncestro(padre);
        int[][] tablero_hijo = n.getTablero();
        if (p.getY() != 7 && p.getX() != 0 && tablero_hijo[p.getY() + 1][p.getX()
                - 1] == 0) {
            Arbol.setHijo(n);
            tablero_hijo[p.getY()][p.getX()] = 0;
            tablero_hijo[p.getY() + 1][p.getX() - 1] = fichaJugador;
            Posicion pfinal = new Posicion(p.getX() - 1, p.getY() + 1);
            Jugada j = new Jugada(p, pfinal);
            n.setJugada(j);
            heuristica h = new heuristica();
            actualizarListasPadre(padre);
            h.heuristica1(n, hl, miasLocal, oponenteLocal);
            n.setTablero(tablero_hijo);
            mostrarMoviminetos(p, pfinal, n);
        }
    }

    private void ascendenteIzquierdo(Posicion p, Node padre, int FichaJugador) {

        int[][] tablero_padre = clonar(padre.getTablero());
        Node n = new Node(tablero_padre, FichaJugador);
        n.setAncestro(padre);
        int[][] tablero_hijo = n.getTablero();
        if (p.getY() != 0 && p.getX() != 0 && tablero_hijo[p.getY() - 1][p.getX()
                - 1] == 0) {
            Arbol.setHijo(n);
            tablero_hijo[p.getY()][p.getX()] = 0;
            tablero_hijo[p.getY() - 1][p.getX() - 1] = fichaJugador;
            Posicion pfinal = new Posicion(p.getX() - 1, p.getY() - 1);
            Jugada j = new Jugada(p, pfinal);
            n.setJugada(j);
            heuristica h = new heuristica();
            actualizarListasPadre(padre);
            h.heuristica1(n, hl, miasLocal, oponenteLocal);
            n.setTablero(tablero_hijo);
            mostrarMoviminetos(p, pfinal, n);
        }
    }

    private void ascendenteDerecha(Posicion p, Node padre, int FichaJugador) {
        int[][] tablero_padre = clonar(padre.getTablero());
        Node n = new Node(tablero_padre, FichaJugador);
        n.setAncestro(padre);
        int[][] tablero_hijo = n.getTablero();
        if (p.getY() != 0 && p.getX() != 7 && tablero_hijo[p.getY() - 1][p.getX()
                + 1] == 0) {
            Arbol.setHijo(n);
            tablero_hijo[p.getY()][p.getX()] = 0;
            tablero_hijo[p.getY() - 1][p.getX() + 1] = fichaJugador;
            Posicion pfinal = new Posicion(p.getX() + 1, p.getY() - 1);
            Jugada j = new Jugada(p, pfinal);
            n.setJugada(j);
            heuristica h = new heuristica();
            actualizarListasPadre(padre);
            h.heuristica1(n, hl, miasLocal, oponenteLocal);
            n.setTablero(tablero_hijo);
            mostrarMoviminetos(p, pfinal, n);
        }
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc="INSERTAR FICHAS">
    public Posicion[] crearInserciones(int[][] tablero_hijo, Posicion proximo) {

        return insertarFichas(tablero_hijo, proximo);
    }

    public Posicion[] insertarFichas(int[][] tablero_hijo, Posicion p) {

        int dimension = tablero_hijo.length;
        Posicion pfinal = new Posicion();
        Posicion proximo = new Posicion();
        int k = 0;
        boolean flag = true;
        for (int j = p.getY(); j < dimension; j++) {
            if (flag) {
                k = p.getX();
            } else {
                k = 0;
            }
            while (k < dimension) {
                flag = false;
                if (tablero_hijo[j][k] == 0) {
                    tablero_hijo[j][k] = fichaJugador;
                    pfinal.setY(j);
                    pfinal.setX(k);
                    proximo.setY(k < dimension - 1 ? j : j + 1);//j=1
                    proximo.setX(k < dimension - 1 ? k + 1 : 0);
                    Posicion[] proxFin = {pfinal, proximo};
                    return proxFin;
                }
                k++;
            }
        }
        return null;
    }
    //</editor-fold>

    public void actualizarListasPadre(Node padre) {
        if (padre.ancestro == null) {
            miasLocal = (ArrayList<Posicion>) Arbol.misFichas.clone();
            oponenteLocal = (ArrayList<Posicion>) Arbol.fichasOponente.clone();
        } else {
            ArrayList<Posicion> aux = (ArrayList<Posicion>) Arbol.misFichas.
                    clone();
            for (Posicion posicion : aux) {
                if (posicion.equals(padre.getJugada().getPosicionInicial())) {
                    posicion = padre.getJugada().getPosicionFinal();
                }
            }
            oponenteLocal = aux;
            miasLocal = (ArrayList<Posicion>) Arbol.fichasOponente.clone();
        }
    }

    public boolean equals(Node n) {
        if (n.equals(this)) {
            return true;
        } else {
            return false;
        }
    }

    public int getPuntuacion() {
        return Puntuacion;
    }

    // Check for ancestors
    public boolean tieneAntecesor() {
        if (ancestro != null) {
            return true;
        } else {
            return false;
        }
    }

//    public void add(int[][] tablero, int[] jugada, int fichaJugador,
//            boolean esMover) {
//        Node nuevoHijo = new Node(tablero, jugada, fichaJugador, esMover);
//        Hijos.add(nuevoHijo);
//    }
    public Node getNodo(int i) {
        return Hijos.get(i).getThis();
    }

    public int cantidadHijos() {
        return Hijos.size();
    }

    public Node getThis() {
        return this;
    }
} // End class Node
